home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / main / fuelcen.c < prev    next >
Text File  |  1998-03-03  |  46KB  |  1,334 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/main/fuelcen.c,v $
  15.  * $Revision: 1.1.1.1 $
  16.  * $Author: nobody $
  17.  * $Date: 1998/03/03 15:12:14 $
  18.  * 
  19.  * Functions for refueling centers.
  20.  * 
  21.  * $Log: fuelcen.c,v $
  22.  * Revision 1.1.1.1  1998/03/03 15:12:14  nobody
  23.  * reimport after crash from backup
  24.  *
  25.  * Revision 1.1.1.1  1998/02/13  20:20:52  hfrieden
  26.  * Initial Import
  27.  *
  28.  * Revision 2.3  1995/03/21  14:38:40  john
  29.  * Ifdef'd out the NETWORK code.
  30.  * 
  31.  * Revision 2.2  1995/03/06  15:23:09  john
  32.  * New screen techniques.
  33.  * 
  34.  * Revision 2.1  1995/02/27  13:13:26  john
  35.  * Removed floating point.
  36.  * 
  37.  * Revision 2.0  1995/02/27  11:27:20  john
  38.  * New version 2.0, which has no anonymous unions, builds with
  39.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  40.  * 
  41.  * Revision 1.159  1995/02/22  13:48:10  allender
  42.  * remove anonymous unions in object structure
  43.  * 
  44.  * Revision 1.158  1995/02/08  11:37:48  mike
  45.  * Check for failures in call to obj_create.
  46.  * 
  47.  * Revision 1.157  1995/02/07  20:39:39  mike
  48.  * fix toasters in multiplayer
  49.  * 
  50.  * 
  51.  * Revision 1.156  1995/02/02  18:40:10  john
  52.  * Fixed bug with full screen cockpit flashing non-white.
  53.  * 
  54.  * Revision 1.155  1995/01/28  15:27:22  yuan
  55.  * Make sure fuelcen nums are valid.
  56.  * 
  57.  * Revision 1.154  1995/01/03  14:26:23  rob
  58.  * Better ifdef for robot centers.
  59.  * 
  60.  * Revision 1.153  1995/01/03  11:27:49  rob
  61.  * Added include of fuelcen.c
  62.  * 
  63.  * Revision 1.152  1995/01/03  09:47:22  john
  64.  * Some ifdef SHAREWARE lines.
  65.  * 
  66.  * Revision 1.151  1995/01/02  21:02:07  rob
  67.  * added matcen support for coop/multirobot.
  68.  * 
  69.  * Revision 1.150  1994/12/15  18:31:22  mike
  70.  * fix confusing precedence problems.
  71.  * 
  72.  * Revision 1.149  1994/12/15  13:04:22  mike
  73.  * Replace Players[Player_num].time_total references with GameTime.
  74.  * 
  75.  * Revision 1.148  1994/12/15  03:05:18  matt
  76.  * Added error checking for NULL return from object_create_explosion()
  77.  * 
  78.  * Revision 1.147  1994/12/13  19:49:12  rob
  79.  * Made the fuelcen noise quieter.
  80.  * 
  81.  * Revision 1.146  1994/12/13  12:03:18  john
  82.  * Made the warning sirens not start until after "desccruction
  83.  * secquence activated voice".
  84.  * 
  85.  * Revision 1.145  1994/12/12  17:18:30  mike
  86.  * make warning siren louder.
  87.  * 
  88.  * Revision 1.144  1994/12/11  23:18:04  john
  89.  * Added -nomusic.
  90.  * Added RealFrameTime.
  91.  * Put in a pause when sound initialization error.
  92.  * Made controlcen countdown and framerate use RealFrameTime.
  93.  * 
  94.  * Revision 1.143  1994/12/11  14:10:16  mike
  95.  * louder sounds.
  96.  * 
  97.  * Revision 1.142  1994/12/06  11:33:19  yuan
  98.  * Fixed bug with fueling when above 100.
  99.  * 
  100.  * Revision 1.141  1994/12/05  23:37:14  matt
  101.  * Took out calls to warning() function
  102.  * 
  103.  * Revision 1.140  1994/12/05  23:19:18  yuan
  104.  * Fixed fuel center refuelers..
  105.  * 
  106.  * Revision 1.139  1994/12/03  12:48:12  mike
  107.  * diminish rocking due to control center destruction.
  108.  * 
  109.  * Revision 1.138  1994/12/02  23:30:32  mike
  110.  * fix bumpiness after toasting control center.
  111.  * 
  112.  * Revision 1.137  1994/12/02  22:48:14  mike
  113.  * rock the ship after toasting the control center!
  114.  * 
  115.  * Revision 1.136  1994/12/02  17:12:11  rob
  116.  * Fixed countdown sounds.
  117.  * 
  118.  * Revision 1.135  1994/11/29  20:59:43  rob
  119.  * Don't run out of fuel in net games (don't want to sync it between machines)
  120.  * 
  121.  * Revision 1.134  1994/11/29  19:10:57  john
  122.  * Took out debugging mprintf.
  123.  * 
  124.  * Revision 1.133  1994/11/29  13:19:40  john
  125.  * Made voice for "destruction actived in t-"
  126.  * be at 12.75 secs.
  127.  * 
  128.  * Revision 1.132  1994/11/29  12:19:46  john
  129.  * MAde the "Mine desctruction will commence"
  130.  * voice play at 12.5 secs.
  131.  * 
  132.  * Revision 1.131  1994/11/29  12:12:54  adam
  133.  * *** empty log message ***
  134.  * 
  135.  * Revision 1.130  1994/11/28  21:04:26  rob
  136.  * Added code to cast noise when player refuels.
  137.  * 
  138.  * Revision 1.129  1994/11/27  23:15:04  matt
  139.  * Made changes for new mprintf calling convention
  140.  * 
  141.  * Revision 1.128  1994/11/21  16:27:51  mike
  142.  * debug code for morphing.
  143.  * 
  144.  * Revision 1.127  1994/11/21  12:33:50  matt
  145.  * For control center explosions, use small fireball, not pseudo-random vclip
  146.  * 
  147.  * Revision 1.126  1994/11/20  22:12:15  mike
  148.  * Fix bug in initializing materialization centers.
  149.  * 
  150.  * Revision 1.125  1994/11/19  15:18:22  mike
  151.  * rip out unused code and data.
  152.  * 
  153.  * Revision 1.124  1994/11/08  12:18:59  mike
  154.  * Initialize Fuelcen_seconds_left.
  155.  * 
  156.  * Revision 1.123  1994/10/30  14:12:33  mike
  157.  * rip out repair center stuff
  158.  * 
  159.  * Revision 1.122  1994/10/28  14:42:45  john
  160.  * Added sound volumes to all sound calls.
  161.  * 
  162.  * Revision 1.121  1994/10/16  12:44:02  mike
  163.  * Make time to exit mine after control center destruction diff level dependent.
  164.  * 
  165.  * Revision 1.120  1994/10/09  22:03:26  mike
  166.  * Adapt to new create_n_segment_path parameters.
  167.  * 
  168.  * Revision 1.119  1994/10/06  14:52:42  mike
  169.  * Remove last of ability to damage fuel centers.
  170.  * 
  171.  * Revision 1.118  1994/10/06  14:08:45  matt
  172.  * Made morph flash effect get orientation from segment
  173.  * 
  174.  * Revision 1.117  1994/10/05  16:09:03  mike
  175.  * Put debugging code into matcen/fuelcen synchronization problem.
  176.  * 
  177.  * Revision 1.116  1994/10/04  15:32:41  john
  178.  * Took out the old PLAY_SOUND??? code and replaced it
  179.  * with direct calls into digi_link_??? so that all sounds
  180.  * can be made 3d.
  181.  * 
  182.  * Revision 1.115  1994/10/03  23:37:57  mike
  183.  * Clean up this mess of confusion to the point where maybe matcens actually work.
  184.  * 
  185.  * Revision 1.114  1994/10/03  13:34:40  matt
  186.  * Added new (and hopefully better) game sequencing functions
  187.  * 
  188.  * Revision 1.113  1994/09/30  14:41:57  matt
  189.  * Fixed bug as per Mike's instructions
  190.  * 
  191.  * Revision 1.112  1994/09/30  00:37:33  mike
  192.  * Balance materialization centers.
  193.  * 
  194.  * Revision 1.111  1994/09/28  23:12:52  matt
  195.  * Macroized palette flash system
  196.  * 
  197.  * Revision 1.110  1994/09/27  15:42:31  mike
  198.  * Add names of Specials.
  199.  * 
  200.  * Revision 1.109  1994/09/27  00:02:23  mike
  201.  * Yet more materialization center stuff.
  202.  * 
  203.  * Revision 1.108  1994/09/26  11:26:23  mike
  204.  * Balance materialization centers.
  205.  * 
  206.  * Revision 1.107  1994/09/25  23:40:47  matt
  207.  * Changed the object load & save code to read/write the structure fields one
  208.  * at a time (rather than the whole structure at once).  This mean that the
  209.  * object structure can be changed without breaking the load/save functions.
  210.  * As a result of this change, the local_object data can be and has been 
  211.  * incorporated into the object array.  Also, timeleft is now a property 
  212.  * of all objects, and the object structure has been otherwise cleaned up.
  213.  * 
  214.  * Revision 1.106  1994/09/25  15:55:58  mike
  215.  * Balance materialization centers, make them emit light, make them re-triggerable after awhile.
  216.  * 
  217.  * Revision 1.105  1994/09/24  17:42:33  mike
  218.  * Making materialization centers be activated by triggers and balancing them.
  219.  * 
  220.  * Revision 1.104  1994/09/24  14:16:06  mike
  221.  * Support new network constants.
  222.  * 
  223.  * Revision 1.103  1994/09/20  19:14:40  john
  224.  * Massaged the sound system; used a better formula for determining
  225.  * which l/r balance, also, put in Mike's stuff that searches for a connection
  226.  * between the 2 sounds' segments, stopping for closed doors, etc.
  227.  * 
  228.  * Revision 1.102  1994/09/17  01:40:51  matt
  229.  * Added status bar/sizable window mode, and in the process revamped the
  230.  * whole cockpit mode system.
  231.  * 
  232.  * Revision 1.101  1994/08/31  20:57:25  matt
  233.  * Cleaned up endlevel/death code
  234.  * 
  235.  * Revision 1.100  1994/08/30  17:54:20  mike
  236.  * Slow down rate of creation of objects by materialization centers.
  237.  * 
  238.  * Revision 1.99  1994/08/29  11:47:01  john
  239.  * Added warning if no control centers in mine.
  240.  * 
  241.  */
  242.  
  243.  
  244. #pragma off (unreferenced)
  245. static char rcsid[] = "$Id: fuelcen.c,v 1.1.1.1 1998/03/03 15:12:14 nobody Exp $";
  246. #pragma on (unreferenced)
  247.  
  248. #include <stdio.h>
  249. #include <stdlib.h>
  250. #include <math.h>
  251. #include <string.h>
  252.  
  253. #include "fuelcen.h"
  254. #include "gameseg.h"
  255. #include "game.h"        // For FrameTime
  256. #include "error.h"
  257. #include "mono.h"
  258. #include "gauges.h"
  259. #include "vclip.h"
  260. #include "fireball.h"
  261. #include "robot.h"
  262.  
  263. #include "wall.h"
  264. #include "sounds.h"
  265. #include "morph.h"
  266. #include "3d.h"
  267. #include "bm.h"
  268. #include "polyobj.h"
  269. #include "ai.h"
  270. #include "gamemine.h"
  271. #include "gamesave.h"
  272. #include "player.h"
  273. #include "collide.h"
  274. #include "laser.h"
  275. #include "network.h"
  276. #include "multi.h"
  277. #include "multibot.h"
  278.  
  279. // The max number of fuel stations per mine.
  280.  
  281. fix Fuelcen_refill_speed = i2f(1);
  282. fix Fuelcen_give_amount = i2f(25);
  283. fix Fuelcen_max_amount = i2f(100);
  284.  
  285. // Every time a robot is created in the morphing code, it decreases capacity of the morpher
  286. // by this amount... when capacity gets to 0, no more morphers...
  287. fix EnergyToCreateOneRobot = i2f(1);
  288.  
  289. int Fuelcen_control_center_destroyed = 0;
  290. int Fuelcen_seconds_left = 0;
  291.  
  292. #define MATCEN_HP_DEFAULT            F1_0*500; // Hitpoints
  293. #define MATCEN_INTERVAL_DEFAULT    F1_0*5;    //  5 seconds
  294.  
  295. matcen_info RobotCenters[MAX_ROBOT_CENTERS];
  296. int Num_robot_centers;
  297.  
  298. control_center_triggers ControlCenterTriggers;
  299.  
  300. FuelCenter Station[MAX_NUM_FUELCENS];
  301. int Num_fuelcenters = 0;
  302.  
  303. segment * PlayerSegment= NULL;
  304.  
  305. #ifdef EDITOR
  306. char    Special_names[MAX_CENTER_TYPES][11] = {
  307.     "NOTHING   ",
  308.     "FUELCEN   ",
  309.     "REPAIRCEN ",
  310.     "CONTROLCEN",
  311.     "ROBOTMAKER",
  312. };
  313. #endif
  314.  
  315. //------------------------------------------------------------
  316. // Resets all fuel center info
  317. void fuelcen_reset()
  318. {
  319.     int i;
  320.  
  321.     Num_fuelcenters = 0;
  322.     //mprintf( (0, "All fuel centers reset.\n"));
  323.  
  324.     for(i=0; i<MAX_SEGMENTS; i++ )
  325.         Segments[i].special = SEGMENT_IS_NOTHING;
  326.  
  327.     Fuelcen_control_center_destroyed = 0;
  328.     Num_robot_centers = 0;
  329.  
  330. }
  331.  
  332. #ifndef NDEBUG        //this is sometimes called by people from the debugger
  333. void reset_all_robot_centers() 
  334. {
  335.     int i;
  336.  
  337.     // Remove all materialization centers
  338.     for (i=0; i<Num_segments; i++)
  339.         if (Segments[i].special == SEGMENT_IS_ROBOTMAKER) {
  340.             Segments[i].special = SEGMENT_IS_NOTHING;
  341.             Segments[i].matcen_num = -1;
  342.         }
  343. }
  344. #endif
  345.  
  346. //------------------------------------------------------------
  347. // Turns a segment into a fully charged up fuel center...
  348. void fuelcen_create( segment * segp)
  349. {
  350.     int    station_type;
  351.  
  352.     station_type = segp->special;
  353.  
  354.     switch( station_type )    {
  355.     case SEGMENT_IS_NOTHING:
  356.         return;
  357.     case SEGMENT_IS_FUELCEN:
  358.     case SEGMENT_IS_REPAIRCEN:
  359.     case SEGMENT_IS_CONTROLCEN:
  360.     case SEGMENT_IS_ROBOTMAKER:
  361.         break;
  362.     default:
  363.         Error( "Invalid station type %d in fuelcen.c\n", station_type );
  364.     }
  365.  
  366.     Assert( (segp != NULL) );
  367.     if ( segp == NULL ) return;
  368.  
  369.     Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
  370.     Assert( Num_fuelcenters > -1 );
  371.  
  372.     segp->value = Num_fuelcenters;
  373.     Station[Num_fuelcenters].Type = station_type;
  374.     Station[Num_fuelcenters].MaxCapacity = Fuelcen_max_amount;
  375.     Station[Num_fuelcenters].Capacity = Station[Num_fuelcenters].MaxCapacity;
  376.     Station[Num_fuelcenters].segnum = segp-Segments;
  377.     Station[Num_fuelcenters].Timer = -1;
  378.     Station[Num_fuelcenters].Flag = 0;
  379. //    Station[Num_fuelcenters].NextRobotType = -1;
  380. //    Station[Num_fuelcenters].last_created_obj=NULL;
  381. //    Station[Num_fuelcenters].last_created_sig = -1;
  382.     compute_segment_center(&Station[Num_fuelcenters].Center, segp );
  383.  
  384. //    if (station_type == SEGMENT_IS_ROBOTMAKER)
  385. //        Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
  386.  
  387.     //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
  388.     Num_fuelcenters++;
  389. }
  390.  
  391. //------------------------------------------------------------
  392. // Adds a matcen that already is a special type into the Station array.
  393. // This function is separate from other fuelcens because we don't want values reset.
  394. void matcen_create( segment * segp)
  395. {
  396.     int    station_type = segp->special;
  397.  
  398.     Assert( (segp != NULL) );
  399.     Assert(station_type == SEGMENT_IS_ROBOTMAKER);
  400.     if ( segp == NULL ) return;
  401.  
  402.     Assert( Num_fuelcenters < MAX_NUM_FUELCENS );
  403.     Assert( Num_fuelcenters > -1 );
  404.  
  405.     segp->value = Num_fuelcenters;
  406.     Station[Num_fuelcenters].Type = station_type;
  407.     Station[Num_fuelcenters].Capacity = i2f(Difficulty_level + 3);
  408.     Station[Num_fuelcenters].MaxCapacity = Station[Num_fuelcenters].Capacity;
  409.  
  410.     Station[Num_fuelcenters].segnum = segp-Segments;
  411.     Station[Num_fuelcenters].Timer = -1;
  412.     Station[Num_fuelcenters].Flag = 0;
  413. //    Station[Num_fuelcenters].NextRobotType = -1;
  414. //    Station[Num_fuelcenters].last_created_obj=NULL;
  415. //    Station[Num_fuelcenters].last_created_sig = -1;
  416.     compute_segment_center(&Station[Num_fuelcenters].Center, segp );
  417.  
  418.     segp->matcen_num = Num_robot_centers;
  419.     Num_robot_centers++;
  420.  
  421.     RobotCenters[segp->matcen_num].hit_points = MATCEN_HP_DEFAULT;
  422.     RobotCenters[segp->matcen_num].interval = MATCEN_INTERVAL_DEFAULT;
  423.     RobotCenters[segp->matcen_num].segnum = segp-Segments;
  424.     RobotCenters[segp->matcen_num].fuelcen_num = Num_fuelcenters;
  425.  
  426.     //mprintf( (0, "Segment %d is assigned to be fuel center %d.\n", Station[Num_fuelcenters].segnum, Num_fuelcenters ));
  427.     Num_fuelcenters++;
  428. }
  429.  
  430. //------------------------------------------------------------
  431. // Adds a segment that already is a special type into the Station array.
  432. void fuelcen_activate( segment * segp, int station_type )
  433. {
  434.     segp->special = station_type;
  435.  
  436.     if (segp->special == SEGMENT_IS_ROBOTMAKER)
  437.         matcen_create( segp);
  438.     else
  439.         fuelcen_create( segp);
  440.     
  441. }
  442.  
  443. //    The lower this number is, the more quickly the center can be re-triggered.
  444. //    If it's too low, it can mean all the robots won't be put out, but for about 5
  445. //    robots, that's not real likely.
  446. #define    MATCEN_LIFE (i2f(30-2*Difficulty_level))
  447.  
  448. //------------------------------------------------------------
  449. //    Trigger (enable) the materialization center in segment segnum
  450. void trigger_matcen(int segnum)
  451. {
  452.     segment        *segp = &Segments[segnum];
  453.     vms_vector    pos, delta;
  454.     FuelCenter    *robotcen;
  455.     int            objnum;
  456.  
  457.     mprintf((0, "Trigger matcen, segment %i\n", segnum));
  458.  
  459.     Assert(segp->special == SEGMENT_IS_ROBOTMAKER);
  460.     Assert(segp->matcen_num < Num_fuelcenters);
  461.     Assert((segp->matcen_num >= 0) && (segp->matcen_num <= Highest_segment_index));
  462.  
  463.     robotcen = &Station[RobotCenters[segp->matcen_num].fuelcen_num];
  464.  
  465.     if (robotcen->Enabled == 1)
  466.         return;
  467.  
  468.     if (!robotcen->Lives)
  469.         return;
  470.  
  471.     robotcen->Lives--;
  472.     robotcen->Timer = F1_0*1000;    //    Make sure the first robot gets emitted right away.
  473.     robotcen->Enabled = 1;            //    Say this center is enabled, it can create robots.
  474.     robotcen->Capacity = i2f(Difficulty_level + 3);
  475.     robotcen->Disable_time = MATCEN_LIFE;
  476.  
  477.     //    Create a bright object in the segment.
  478.     pos = robotcen->Center;
  479.     vm_vec_sub(&delta, &Vertices[Segments[segnum].verts[0]], &robotcen->Center);
  480.     vm_vec_scale_add2(&pos, &delta, F1_0/2);
  481.     objnum = obj_create( OBJ_LIGHT, 0, segnum, &pos, NULL, 0, CT_LIGHT, MT_NONE, RT_NONE );
  482.     if (objnum != -1) {
  483.         Objects[objnum].lifeleft = MATCEN_LIFE;
  484.         Objects[objnum].ctype.light_info.intensity = i2f(8);    //    Light cast by a fuelcen.
  485.     } else {
  486.         mprintf((1, "Can't create invisible flare for matcen.\n"));
  487.         Int3();
  488.     }
  489. //    mprintf((0, "Created invisibile flare, object=%i, segment=%i, pos=%7.3f %7.3f%7.3f\n", objnum, segnum, f2fl(pos.x), f2fl(pos.y), f2fl(pos.z)));
  490. }
  491.  
  492. #ifdef EDITOR
  493. //------------------------------------------------------------
  494. // Takes away a segment's fuel center properties.
  495. //    Deletes the segment point entry in the FuelCenter list.
  496. void fuelcen_delete( segment * segp )
  497. {
  498.     int i, j;
  499.  
  500. Restart: ;
  501.  
  502.     for (i=0; i<Num_fuelcenters; i++ )    {
  503.         if ( Station[i].segnum == segp-Segments )    {
  504.  
  505.             // If Robot maker is deleted, fix Segments and RobotCenters.
  506.             if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
  507.                 Num_robot_centers--;
  508.  
  509.                 for (j=segp->matcen_num; j<Num_robot_centers; j++)
  510.                     RobotCenters[j] = RobotCenters[j+1];
  511.  
  512.                 for (j=0; j<Num_fuelcenters; j++) {
  513.                     if ( Station[j].Type == SEGMENT_IS_ROBOTMAKER )
  514.                         if ( Segments[Station[j].segnum].matcen_num > segp->matcen_num )
  515.                             Segments[Station[j].segnum].matcen_num--;
  516.                 }
  517.             }
  518.         
  519.             Num_fuelcenters--;
  520.             for (j=i; j<Num_fuelcenters; j++ )    {
  521.                 Station[i] = Station[i+1];
  522.                 Segments[Station[i].segnum].value = i;
  523.             }
  524.             segp->special = 0;
  525.             goto Restart;
  526.         }
  527.     }
  528.  
  529. }
  530. #endif
  531.  
  532. #define    ROBOT_GEN_TIME (i2f(5))
  533.  
  534. object * create_morph_robot( segment *segp, vms_vector *object_pos, int object_id)
  535. {
  536.     short        objnum;
  537.     object    *obj;
  538.     int        default_behavior;
  539.  
  540.     Players[Player_num].num_robots_level++;
  541.     Players[Player_num].num_robots_total++;
  542.  
  543.     objnum = obj_create(OBJ_ROBOT, object_id, segp-Segments, object_pos,
  544.                 &vmd_identity_matrix, Polygon_models[Robot_info[object_id].model_num].rad,
  545.                 CT_AI, MT_PHYSICS, RT_POLYOBJ);
  546.  
  547.     if ( objnum < 0 ) {
  548.         mprintf((1, "Can't create morph robot.  Aborting morph.\n"));
  549.         Int3();
  550.         return NULL;
  551.     }
  552.  
  553.     obj = &Objects[objnum];
  554.  
  555.     //Set polygon-object-specific data 
  556.  
  557.     obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
  558.     obj->rtype.pobj_info.subobj_flags = 0;
  559.  
  560.     //set Physics info
  561.  
  562.     obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
  563.     obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
  564.  
  565.     obj->mtype.phys_info.flags |= (PF_LEVELLING);
  566.  
  567.     obj->shields = Robot_info[obj->id].strength;
  568.     
  569.     default_behavior = AIB_NORMAL;
  570.     if (object_id == 10)                        //    This is a toaster guy!
  571.         default_behavior = AIB_RUN_FROM;
  572.  
  573.     init_ai_object(obj-Objects, default_behavior, -1 );        //    Note, -1 = segment this robot goes to to hide, should probably be something useful
  574.  
  575.     create_n_segment_path(obj, 6, -1);        //    Create a 6 segment path from creation point.
  576.  
  577.     if (default_behavior == AIB_RUN_FROM)
  578.         Ai_local_info[objnum].mode = AIM_RUN_FROM_OBJECT;
  579.  
  580.     return obj;
  581. }
  582.  
  583. int Num_extry_robots = 15;
  584.  
  585. #ifndef NDEBUG
  586. int    FrameCount_last_msg = 0;
  587. #endif
  588.  
  589. //    ----------------------------------------------------------------------------------------------------------
  590. void robotmaker_proc( FuelCenter * robotcen )
  591. {
  592.     fix        dist_to_player;
  593.     vms_vector    cur_object_loc; //, direction;
  594.     int        matcen_num, segnum, objnum;
  595.     object    *obj;
  596.     fix        top_time;
  597.     vms_vector    direction;
  598.  
  599.     if (robotcen->Enabled == 0)
  600.         return;
  601.  
  602.     if (robotcen->Disable_time > 0) {
  603.         robotcen->Disable_time -= FrameTime;
  604.         if (robotcen->Disable_time <= 0) {
  605.             mprintf((0, "Robot center #%i gets disabled due to time running out.\n", robotcen-Station));
  606.             robotcen->Enabled = 0;
  607.         }
  608.     }
  609.  
  610.     // mprintf((0, "Capacity of robot maker #%i is %i\n", robotcen - Station, robotcen->Capacity));
  611.  
  612.     //    No robot making in multiplayer mode.
  613. #ifdef NETWORK
  614. #ifndef SHAREWARE
  615.     if ((Game_mode & GM_MULTI) && (!(Game_mode & GM_MULTI_ROBOTS) || !network_i_am_master()))
  616.         return;
  617. #else
  618.     if (Game_mode & GM_MULTI)
  619.         return;
  620. #endif
  621. #endif
  622.  
  623.     // Wait until transmorgafier has capacity to make a robot...
  624.     if ( robotcen->Capacity <= 0 ) {
  625.         return;
  626.     }
  627.  
  628.     matcen_num = Segments[robotcen->segnum].matcen_num;
  629.     //mprintf((0, "Robotmaker #%i flags = %8x\n", matcen_num, RobotCenters[matcen_num].robot_flags));
  630.  
  631.     if ( matcen_num == -1 ) {
  632.         mprintf((0, "Non-functional robotcen at %d\n", robotcen->segnum));
  633.         return;
  634.     }
  635.  
  636.     if (RobotCenters[matcen_num].robot_flags == 0) {
  637.         //mprintf((0, "robot_flags = 0 at robot maker #%i\n", RobotCenters[matcen_num].robot_flags));
  638.         return;
  639.     }
  640.  
  641.     // Wait until we have a free slot for this puppy...
  642.    //      <<<<<<<<<<<<<<<< Num robots in mine >>>>>>>>>>>>>>>>>>>>>>>>>>    <<<<<<<<<<<< Max robots in mine >>>>>>>>>>>>>>>
  643.     if ( (Players[Player_num].num_robots_level - Players[Player_num].num_kills_level) >= (Gamesave_num_org_robots + Num_extry_robots ) ) {
  644.         #ifndef NDEBUG
  645.         if (FrameCount > FrameCount_last_msg + 20) {
  646.             mprintf((0, "Cannot morph until you kill one!\n"));
  647.             FrameCount_last_msg = FrameCount;
  648.         }
  649.         #endif
  650.         return;
  651.     }
  652.  
  653.     robotcen->Timer += FrameTime;
  654.  
  655.     switch( robotcen->Flag )    {
  656.     case 0:        // Wait until next robot can generate
  657.         if (Game_mode & GM_MULTI) 
  658.         {
  659.             top_time = ROBOT_GEN_TIME;    
  660.         }
  661.         else 
  662.         {
  663.             dist_to_player = vm_vec_dist_quick( &ConsoleObject->pos, &robotcen->Center );
  664.             top_time = dist_to_player/64 + rand() * 2 + F1_0*2;
  665.             if ( top_time > ROBOT_GEN_TIME )
  666.                 top_time = ROBOT_GEN_TIME + rand();
  667.             if ( top_time < F1_0*2 )
  668.                 top_time = F1_0*3/2 + rand()*2;
  669.         }
  670.  
  671.          // mprintf( (0, "Time between morphs %d seconds, dist_to_player = %7.3f\n", f2i(top_time), f2fl(dist_to_player) ));
  672.  
  673.         if (robotcen->Timer > top_time )    {
  674.             int    count=0;
  675.             int    i, my_station_num = robotcen-Station;
  676.             object *obj;
  677.  
  678.             //    Make sure this robotmaker hasn't put out its max without having any of them killed.
  679.             for (i=0; i<=Highest_object_index; i++)
  680.                 if (Objects[i].type == OBJ_ROBOT)
  681.                     if ((Objects[i].matcen_creator^0x80) == my_station_num)
  682.                         count++;
  683.             if (count > Difficulty_level + 3) {
  684.                 mprintf((0, "Cannot morph: center %i has already put out %i robots.\n", my_station_num, count));
  685.                 robotcen->Timer /= 2;
  686.                 return;
  687.             }
  688.  
  689.             //    Whack on any robot or player in the matcen segment.
  690.             count=0;
  691.             segnum = robotcen->segnum;
  692.             for (objnum=Segments[segnum].objects;objnum!=-1;objnum=Objects[objnum].next)    {
  693.                 count++;
  694.                 if ( count > MAX_OBJECTS )    {
  695.                     mprintf((0, "Object list in segment %d is circular.", segnum ));
  696.                     Int3();
  697.                     return;
  698.                 }
  699.                 if (Objects[objnum].type==OBJ_ROBOT) {
  700.                     collide_robot_and_materialization_center(&Objects[objnum]);
  701.                     robotcen->Timer = top_time/2;
  702.                     return;
  703.                 } else if (Objects[objnum].type==OBJ_PLAYER ) {
  704.                     collide_player_and_materialization_center(&Objects[objnum]);
  705.                     robotcen->Timer = top_time/2;
  706.                     return;
  707.                 }
  708.             }
  709.  
  710.             compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
  711.             // HACK!!! The 10 under here should be something equal to the 1/2 the size of the segment.
  712.             obj = object_create_explosion(robotcen->segnum, &cur_object_loc, i2f(10), VCLIP_MORPHING_ROBOT );
  713.  
  714.             if (obj)
  715.                 extract_orient_from_segment(&obj->orient,&Segments[robotcen->segnum]);
  716.  
  717.             if ( Vclip[VCLIP_MORPHING_ROBOT].sound_num > -1 )        {
  718.                 digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, robotcen->segnum, 0, &cur_object_loc, 0, F1_0 );
  719.             }
  720.             robotcen->Flag    = 1;
  721.             robotcen->Timer = 0;
  722.  
  723.         }
  724.         break;
  725.     case 1:            // Wait until 1/2 second after VCLIP started.
  726.         if (robotcen->Timer > (Vclip[VCLIP_MORPHING_ROBOT].play_time/2) )    {
  727.  
  728.             robotcen->Capacity -= EnergyToCreateOneRobot;
  729.             robotcen->Flag = 0;
  730.  
  731.             robotcen->Timer = 0;
  732.             compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
  733.  
  734.             // If this is the first materialization, set to valid robot.
  735.             if (RobotCenters[matcen_num].robot_flags != 0) {
  736.                 int    type;
  737.                 uint    flags;
  738.                 byte    legal_types[32];        //    32 bits in a word, the width of robot_flags.
  739.                 int    num_types, robot_index;
  740.  
  741.                 robot_index = 0;
  742.                 num_types = 0;
  743.                 flags = RobotCenters[matcen_num].robot_flags;
  744.                 while (flags) {
  745.                     if (flags & 1)
  746.                         legal_types[num_types++] = robot_index;
  747.                     flags >>= 1;
  748.                     robot_index++;
  749.                 }
  750.  
  751.                 //mprintf((0, "Flags = %08x, %2i legal types to morph: \n", RobotCenters[matcen_num].robot_flags, num_types));
  752.                 //for (i=0; i<num_types; i++)
  753.                 //    mprintf((0, "%2i ", legal_types[i]));
  754.                 //mprintf((0, "\n"));
  755.  
  756.                 if (num_types == 1)
  757.                     type = legal_types[0];
  758.                 else
  759.                     type = legal_types[(rand() * num_types) / 32768];
  760.  
  761.                 mprintf((0, "Morph: (type = %i) (seg = %i) (capacity = %08x)\n", type, robotcen->segnum, robotcen->Capacity));
  762.                 obj = create_morph_robot(&Segments[robotcen->segnum], &cur_object_loc, type );
  763.                 if (obj != NULL) {
  764. #ifndef SHAREWARE
  765. #ifdef NETWORK
  766.                     if (Game_mode & GM_MULTI)
  767.                         multi_send_create_robot(robotcen-Station, obj-Objects, type);
  768. #endif
  769. #endif
  770.                     obj->matcen_creator = robotcen-Station | 0x80;
  771.  
  772.                     // Make object faces player...
  773.                     vm_vec_sub( &direction, &ConsoleObject->pos,&obj->pos );
  774.                     vm_vector_2_matrix( &obj->orient, &direction, &obj->orient.uvec, NULL);
  775.     
  776.                     morph_start( obj );
  777.                     //robotcen->last_created_obj = obj;
  778.                     //robotcen->last_created_sig = robotcen->last_created_obj->signature;
  779.                 } else
  780.                     mprintf((0, "Warning: create_morph_robot returned NULL (no objects left?)\n"));
  781.  
  782.             }
  783.   
  784.         }
  785.         break;
  786.     default:
  787.         robotcen->Flag = 0;
  788.         robotcen->Timer = 0;
  789.     }
  790. }
  791.  
  792. #define    BASE_CONTROL_CENTER_EXPLOSION_TIME    30
  793. #define    DIFF_CONTROL_CENTER_EXPLOSION_TIME    (BASE_CONTROL_CENTER_EXPLOSION_TIME + (NDL-Difficulty_level-1)*5)
  794.  
  795. #define COUNTDOWN_VOICE_TIME (i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME)-fl2f(12.75))
  796.  
  797. void controlcen_proc( FuelCenter * controlcen )
  798. {
  799.     fix old_time;
  800.     int    fc;
  801.  
  802. //    mprintf( (0, "CCT: %.1f\n", f2fl(controlcen->Timer)));
  803.  
  804.     if (!Fuelcen_control_center_destroyed)    return;
  805.  
  806.     //    Control center destroyed, rock the player's ship.
  807.     fc = Fuelcen_seconds_left;
  808.     if (fc > 16)
  809.         fc = 16;
  810.     ConsoleObject->mtype.phys_info.rotvel.x += fixmul(rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32);
  811.     ConsoleObject->mtype.phys_info.rotvel.z += fixmul(rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32);
  812.     //    Hook in the rumble sound effect here.
  813.  
  814.     old_time = controlcen->Timer;
  815.     controlcen->Timer += RealFrameTime;            //timer_get_approx_seconds
  816.     Fuelcen_seconds_left = DIFF_CONTROL_CENTER_EXPLOSION_TIME - f2i(controlcen->Timer);
  817.     if ( (old_time < COUNTDOWN_VOICE_TIME ) && (controlcen->Timer >= COUNTDOWN_VOICE_TIME) )    {
  818.             digi_play_sample( SOUND_COUNTDOWN_13_SECS, F3_0 );
  819.     }
  820.     if ( f2i(old_time) != f2i(controlcen->Timer) )    {
  821.         if ( (Fuelcen_seconds_left>=0) && (Fuelcen_seconds_left<10) ) 
  822.             digi_play_sample( SOUND_COUNTDOWN_0_SECS+Fuelcen_seconds_left, F3_0 );
  823.         if ( Fuelcen_seconds_left==DIFF_CONTROL_CENTER_EXPLOSION_TIME-1)
  824.             digi_play_sample( SOUND_COUNTDOWN_29_SECS, F3_0 );
  825.     }                        
  826.  
  827.     if (controlcen->Timer < i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME)) {
  828.         vms_vector vp;    //,v,c;
  829.         fix size;
  830.         compute_segment_center(&vp, &Segments[controlcen->segnum]);
  831.         size = (0x50000*f2i(controlcen->Timer)*(FrameTime & 0xF))/16;
  832.         size = controlcen->Timer / (fl2f(0.65));
  833.         old_time = old_time / (fl2f(0.65));
  834.         if (size != old_time && (controlcen->Timer > (5*F1_0) ))        {            // Every 2 seconds!
  835.             //@@object_create_explosion( controlcen->segnum, &vp, size*10, FrameTime & 7);
  836.             object_create_explosion( controlcen->segnum, &vp, size*10, VCLIP_SMALL_EXPLOSION);
  837.             digi_play_sample( SOUND_CONTROL_CENTER_WARNING_SIREN, F3_0 );
  838.         }
  839.     }  else {
  840.         int flash_value;
  841.  
  842.         if (old_time < i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME))
  843.             digi_play_sample( SOUND_MINE_BLEW_UP, F1_0 );
  844.  
  845.         flash_value = f2i( (controlcen->Timer-i2f(DIFF_CONTROL_CENTER_EXPLOSION_TIME))*(64/4));    // 4 seconds to total whiteness
  846.         PALETTE_FLASH_SET(flash_value,flash_value,flash_value);
  847.  
  848.         //gauge_message( "YOU'RE TOO SLOW! THE MINE BLEW UP!" );
  849.         if (PaletteBlueAdd > 64 )    {
  850.             gr_set_current_canvas( NULL );        
  851.             gr_clear_canvas(BM_XRGB(31,31,31));        //make screen all white to match palette effect
  852.             reset_cockpit();                                //force cockpit redraw next time
  853.             reset_palette_add();                            //restore palette for death message
  854.             controlcen->Timer = -1;
  855.             controlcen->MaxCapacity = Fuelcen_max_amount;
  856.             //gauge_message( "Control Center Reset" );
  857.             DoPlayerDead();        //kill_player();
  858.         }                                                                                
  859.     }
  860. }
  861.  
  862. #define M_PI 3.14159
  863.  
  864. //-------------------------------------------------------------
  865. // Called once per frame, replenishes fuel supply.
  866. void fuelcen_update_all()
  867. {
  868.     int i;
  869.     fix AmountToreplenish;
  870.     
  871.     AmountToreplenish = fixmul(FrameTime,Fuelcen_refill_speed);
  872.  
  873.     for (i=0; i<Num_fuelcenters; i++ )    {
  874.         if ( Station[i].Type == SEGMENT_IS_ROBOTMAKER )    {
  875.             if (! (Game_suspended & SUSP_ROBOTS))
  876.                 robotmaker_proc( &Station[i] );
  877.         } else if ( Station[i].Type == SEGMENT_IS_CONTROLCEN )    {
  878.             controlcen_proc( &Station[i] );
  879.     
  880.         } else if ( (Station[i].MaxCapacity > 0) && (PlayerSegment!=&Segments[Station[i].segnum]) )    {
  881.             if ( Station[i].Capacity < Station[i].MaxCapacity )    {
  882.                  Station[i].Capacity += AmountToreplenish;
  883.                 //mprintf( (0, "Fuel center %d replenished to %d.\n", i, f2i(Station[i].Capacity) ));
  884.                 if ( Station[i].Capacity >= Station[i].MaxCapacity )        {
  885.                     Station[i].Capacity = Station[i].MaxCapacity;
  886.                     //gauge_message( "Fuel center is fully recharged!    " );
  887.                 }
  888.             }
  889.         }
  890.     }
  891. }
  892.  
  893. //--unused-- //-------------------------------------------------------------
  894. //--unused-- // replenishes all fuel supplies.
  895. //--unused-- void fuelcen_replenish_all()
  896. //--unused-- {
  897. //--unused--     int i;
  898. //--unused-- 
  899. //--unused--     for (i=0; i<Num_fuelcenters; i++ )    {
  900. //--unused--         Station[i].Capacity = Station[i].MaxCapacity;
  901. //--unused--     }
  902. //--unused--     //mprintf( (0, "All fuel centers are replenished\n" ));
  903. //--unused-- 
  904. //--unused-- }
  905.  
  906. //-------------------------------------------------------------
  907. fix fuelcen_give_fuel(segment *segp, fix MaxAmountCanTake )
  908. {
  909.     Assert( segp != NULL );
  910.  
  911.     PlayerSegment = segp;
  912.  
  913.     if ( (segp) && (segp->special==SEGMENT_IS_FUELCEN) )    {
  914.         fix amount;
  915.  
  916. //        if (Station[segp->value].MaxCapacity<=0)    {
  917. //            HUD_init_message( "Fuelcenter %d is destroyed.", segp->value );
  918. //            return 0;
  919. //        }
  920.  
  921. //        if (Station[segp->value].Capacity<=0)    {
  922. //            HUD_init_message( "Fuelcenter %d is empty.", segp->value );
  923. //            return 0;
  924. //        }
  925.  
  926.         if (MaxAmountCanTake <= 0 )    {
  927. //            //gauge_message( "Fueled up!");
  928.             return 0;
  929.         }
  930.  
  931.         amount = fixmul(FrameTime,Fuelcen_give_amount);
  932.  
  933.         if (amount > MaxAmountCanTake )
  934.             amount = MaxAmountCanTake;
  935.  
  936. //        if (!(Game_mode & GM_MULTI))
  937. //            if ( Station[segp->value].Capacity < amount  )    {
  938. //                amount = Station[segp->value].Capacity;
  939. //                Station[segp->value].Capacity = 0;
  940. //            } else {
  941. //                Station[segp->value].Capacity -= amount;
  942. //            }
  943.  
  944.         digi_play_sample( SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2 );
  945.  
  946.         #ifdef NETWORK
  947.         if (Game_mode & GM_MULTI)
  948.             multi_send_play_sound(SOUND_REFUEL_STATION_GIVING_FUEL, F1_0/2);
  949.         #endif
  950.  
  951.         //HUD_init_message( "Fuelcen %d has %d/%d fuel", segp->value,f2i(Station[segp->value].Capacity),f2i(Station[segp->value].MaxCapacity) );
  952.         return amount;
  953.  
  954.     } else {
  955.         return 0;
  956.     }
  957. }
  958.  
  959. //--unused-- //-----------------------------------------------------------
  960. //--unused-- // Damages a fuel center
  961. //--unused-- void fuelcen_damage(segment *segp, fix damage )
  962. //--unused-- {
  963. //--unused--     //int i;
  964. //--unused--     // int    station_num = segp->value;
  965. //--unused-- 
  966. //--unused--     Assert( segp != NULL );
  967. //--unused--     if ( segp == NULL ) return;
  968. //--unused-- 
  969. //--unused--     mprintf((0, "Obsolete function fuelcen_damage() called with seg=%i, damage=%7.3f\n", segp-Segments, f2fl(damage)));
  970. //--unused--     switch( segp->special )    {
  971. //--unused--     case SEGMENT_IS_NOTHING:
  972. //--unused--         return;
  973. //--unused--     case SEGMENT_IS_ROBOTMAKER:
  974. //--unused-- //--        // Robotmaker hit by laser
  975. //--unused-- //--        if (Station[station_num].MaxCapacity<=0 )    {
  976. //--unused-- //--            // Shooting a already destroyed materializer
  977. //--unused-- //--        } else {
  978. //--unused-- //--            Station[station_num].MaxCapacity -= damage;
  979. //--unused-- //--            if (Station[station_num].Capacity > Station[station_num].MaxCapacity )    {
  980. //--unused-- //--                Station[station_num].Capacity = Station[station_num].MaxCapacity;
  981. //--unused-- //--            }
  982. //--unused-- //--            if (Station[station_num].MaxCapacity <= 0 )    {
  983. //--unused-- //--                Station[station_num].MaxCapacity = 0;
  984. //--unused-- //--                // Robotmaker dead
  985. //--unused-- //--                for (i=0; i<6; i++ )
  986. //--unused-- //--                    segp->sides[i].tmap_num2 = 0;
  987. //--unused-- //--            }
  988. //--unused-- //--        }
  989. //--unused-- //--        //mprintf( (0, "Materializatormografier has %x capacity left\n", Station[station_num].MaxCapacity ));
  990. //--unused--         break;
  991. //--unused--     case SEGMENT_IS_FUELCEN:    
  992. //--unused-- //--        digi_play_sample( SOUND_REFUEL_STATION_HIT );
  993. //--unused-- //--        if (Station[station_num].MaxCapacity>0 )    {
  994. //--unused-- //--            Station[station_num].MaxCapacity -= damage;
  995. //--unused-- //--            if (Station[station_num].Capacity > Station[station_num].MaxCapacity )    {
  996. //--unused-- //--                Station[station_num].Capacity = Station[station_num].MaxCapacity;
  997. //--unused-- //--            }
  998. //--unused-- //--            if (Station[station_num].MaxCapacity <= 0 )    {
  999. //--unused-- //--                Station[station_num].MaxCapacity = 0;
  1000. //--unused-- //--                digi_play_sample( SOUND_REFUEL_STATION_DESTROYED );
  1001. //--unused-- //--            }
  1002. //--unused-- //--        } else {
  1003. //--unused-- //--            Station[station_num].MaxCapacity = 0;
  1004. //--unused-- //--        }
  1005. //--unused-- //--        HUD_init_message( "Fuelcenter %d damaged", station_num );
  1006. //--unused--         break;
  1007. //--unused--     case SEGMENT_IS_REPAIRCEN:
  1008. //--unused--         break;
  1009. //--unused--     case SEGMENT_IS_CONTROLCEN:
  1010. //--unused--         break;
  1011. //--unused--     default:
  1012. //--unused--         Error( "Invalid type in fuelcen.c" );
  1013. //--unused--     }
  1014. //--unused-- }
  1015.  
  1016. //--unused-- //    ----------------------------------------------------------------------------------------------------------
  1017. //--unused-- fixang my_delta_ang(fixang a,fixang b)
  1018. //--unused-- {
  1019. //--unused--     fixang delta0,delta1;
  1020. //--unused-- 
  1021. //--unused--     return (abs(delta0 = a - b) < abs(delta1 = b - a)) ? delta0 : delta1;
  1022. //--unused-- 
  1023. //--unused-- }
  1024.  
  1025. //--unused-- //    ----------------------------------------------------------------------------------------------------------
  1026. //--unused-- //return though which side of seg0 is seg1
  1027. //--unused-- int john_find_connect_side(int seg0,int seg1)
  1028. //--unused-- {
  1029. //--unused--     segment *Seg=&Segments[seg0];
  1030. //--unused--     int i;
  1031. //--unused-- 
  1032. //--unused--     for (i=MAX_SIDES_PER_SEGMENT;i--;) if (Seg->children[i]==seg1) return i;
  1033. //--unused-- 
  1034. //--unused--     return -1;
  1035. //--unused-- }
  1036.  
  1037. //    ----------------------------------------------------------------------------------------------------------
  1038. //--unused-- vms_angvec start_angles, delta_angles, goal_angles;
  1039. //--unused-- vms_vector start_pos, delta_pos, goal_pos;
  1040. //--unused-- int FuelStationSeg;
  1041. //--unused-- fix current_time,delta_time;
  1042. //--unused-- int next_side, side_index;
  1043. //--unused-- int * sidelist;
  1044.  
  1045. //--repair-- int Repairing;
  1046. //--repair-- vms_vector repair_save_uvec;        //the player's upvec when enter repaircen
  1047. //--repair-- object *RepairObj=NULL;        //which object getting repaired
  1048. //--repair-- int disable_repair_center=0;
  1049. //--repair-- fix repair_rate;
  1050. //--repair-- #define FULL_REPAIR_RATE i2f(10)
  1051.  
  1052. //--unused-- ubyte save_control_type,save_movement_type;
  1053.  
  1054. //--unused-- int SideOrderBack[] = {WFRONT, WRIGHT, WTOP, WLEFT, WBOTTOM, WBACK};
  1055. //--unused-- int SideOrderFront[] =  {WBACK, WLEFT, WTOP, WRIGHT, WBOTTOM, WFRONT};
  1056. //--unused-- int SideOrderLeft[] =  { WRIGHT, WBACK, WTOP, WFRONT, WBOTTOM, WLEFT };
  1057. //--unused-- int SideOrderRight[] =  { WLEFT, WFRONT, WTOP, WBACK, WBOTTOM, WRIGHT };
  1058. //--unused-- int SideOrderTop[] =  { WBOTTOM, WLEFT, WBACK, WRIGHT, WFRONT, WTOP };
  1059. //--unused-- int SideOrderBottom[] =  { WTOP, WLEFT, WFRONT, WRIGHT, WBACK, WBOTTOM };
  1060.  
  1061. //--unused-- int SideUpVector[] = {WBOTTOM, WFRONT, WBOTTOM, WFRONT, WBOTTOM, WBOTTOM };
  1062.  
  1063. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1064. //--repair-- void refuel_calc_deltas(object *obj, int next_side, int repair_seg)
  1065. //--repair-- {
  1066. //--repair--     vms_vector nextcenter, headfvec, *headuvec;
  1067. //--repair--     vms_matrix goal_orient;
  1068. //--repair-- 
  1069. //--repair--     // Find time for this movement
  1070. //--repair--     delta_time = F1_0;        // one second...
  1071. //--repair--         
  1072. //--repair--     // Find start and goal position
  1073. //--repair--     start_pos = obj->pos;
  1074. //--repair--     
  1075. //--repair--     // Find delta position to get to goal position
  1076. //--repair--     compute_segment_center(&goal_pos,&Segments[repair_seg]);
  1077. //--repair--     vm_vec_sub( &delta_pos,&goal_pos,&start_pos);
  1078. //--repair--     
  1079. //--repair--     // Find start angles
  1080. //--repair--     //angles_from_vector(&start_angles,&obj->orient.fvec);
  1081. //--repair--     vm_extract_angles_matrix(&start_angles,&obj->orient);
  1082. //--repair--     
  1083. //--repair--     // Find delta angles to get to goal orientation
  1084. //--repair--     med_compute_center_point_on_side(&nextcenter,&Segments[repair_seg],next_side);
  1085. //--repair--     vm_vec_sub(&headfvec,&nextcenter,&goal_pos);
  1086. //--repair--     //mprintf( (0, "Next_side = %d, Head fvec = %d,%d,%d\n", next_side, headfvec.x, headfvec.y, headfvec.z ));
  1087. //--repair-- 
  1088. //--repair--     if (next_side == 5)                        //last side
  1089. //--repair--         headuvec = &repair_save_uvec;
  1090. //--repair--     else
  1091. //--repair--         headuvec = &Segments[repair_seg].sides[SideUpVector[next_side]].normals[0];
  1092. //--repair-- 
  1093. //--repair--     vm_vector_2_matrix(&goal_orient,&headfvec,headuvec,NULL);
  1094. //--repair--     vm_extract_angles_matrix(&goal_angles,&goal_orient);
  1095. //--repair--     delta_angles.p = my_delta_ang(start_angles.p,goal_angles.p);
  1096. //--repair--     delta_angles.b = my_delta_ang(start_angles.b,goal_angles.b);
  1097. //--repair--     delta_angles.h = my_delta_ang(start_angles.h,goal_angles.h);
  1098. //--repair--     current_time = 0;
  1099. //--repair--     Repairing = 0;
  1100. //--repair-- }
  1101. //--repair-- 
  1102. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1103. //--repair-- //if repairing, cut it short
  1104. //--repair-- abort_repair_center()
  1105. //--repair-- {
  1106. //--repair--     if (!RepairObj || side_index==5)
  1107. //--repair--         return;
  1108. //--repair-- 
  1109. //--repair--     current_time = 0;
  1110. //--repair--     side_index = 5;
  1111. //--repair--     next_side = sidelist[side_index];
  1112. //--repair--     refuel_calc_deltas(RepairObj, next_side, FuelStationSeg);
  1113. //--repair-- }
  1114. //--repair-- 
  1115. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1116. //--repair-- void repair_ship_damage()
  1117. //--repair-- {
  1118. //--repair--      //mprintf((0,"Repairing ship damage\n"));
  1119. //--repair-- }
  1120. //--repair-- 
  1121. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1122. //--repair-- int refuel_do_repair_effect( object * obj, int first_time, int repair_seg )    {
  1123. //--repair-- 
  1124. //--repair--     obj->mtype.phys_info.velocity.x = 0;                
  1125. //--repair--     obj->mtype.phys_info.velocity.y = 0;                
  1126. //--repair--     obj->mtype.phys_info.velocity.z = 0;                
  1127. //--repair-- 
  1128. //--repair--     if (first_time)    {
  1129. //--repair--         int entry_side;
  1130. //--repair--         current_time = 0;
  1131. //--repair-- 
  1132. //--repair--         digi_play_sample( SOUND_REPAIR_STATION_PLAYER_ENTERING, F1_0 );
  1133. //--repair-- 
  1134. //--repair--         entry_side = john_find_connect_side(repair_seg,obj->segnum );
  1135. //--repair--         Assert( entry_side > -1 );
  1136. //--repair-- 
  1137. //--repair--         switch( entry_side )    {
  1138. //--repair--         case WBACK: sidelist = SideOrderBack; break;
  1139. //--repair--         case WFRONT: sidelist = SideOrderFront; break;
  1140. //--repair--         case WLEFT: sidelist = SideOrderLeft; break;
  1141. //--repair--         case WRIGHT: sidelist = SideOrderRight; break;
  1142. //--repair--         case WTOP: sidelist = SideOrderTop; break;
  1143. //--repair--         case WBOTTOM: sidelist = SideOrderBottom; break;
  1144. //--repair--         }
  1145. //--repair--         side_index = 0;
  1146. //--repair--         next_side = sidelist[side_index];
  1147. //--repair-- 
  1148. //--repair--         refuel_calc_deltas(obj,next_side, repair_seg);
  1149. //--repair--     } 
  1150. //--repair-- 
  1151. //--repair--     //update shields
  1152. //--repair--     if (Players[Player_num].shields < MAX_SHIELDS) {    //if above max, don't mess with it
  1153. //--repair-- 
  1154. //--repair--         Players[Player_num].shields += fixmul(FrameTime,repair_rate);
  1155. //--repair-- 
  1156. //--repair--         if (Players[Player_num].shields > MAX_SHIELDS)
  1157. //--repair--             Players[Player_num].shields = MAX_SHIELDS;
  1158. //--repair--     }
  1159. //--repair-- 
  1160. //--repair--     current_time += FrameTime;
  1161. //--repair-- 
  1162. //--repair--     if (current_time >= delta_time )    {
  1163. //--repair--         vms_angvec av;
  1164. //--repair--         obj->pos = goal_pos;
  1165. //--repair--         av    = goal_angles;
  1166. //--repair--         vm_angles_2_matrix(&obj->orient,&av);
  1167. //--repair-- 
  1168. //--repair--         if (side_index >= 5 )    
  1169. //--repair--             return 1;        // Done being repaired...
  1170. //--repair-- 
  1171. //--repair--         if (Repairing==0)        {
  1172. //--repair--             //mprintf( (0, "<MACHINE EFFECT ON SIDE %d>\n", next_side ));
  1173. //--repair--             //digi_play_sample( SOUND_REPAIR_STATION_FIXING );
  1174. //--repair--             Repairing=1;
  1175. //--repair-- 
  1176. //--repair--             switch( next_side )    {
  1177. //--repair--             case 0:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
  1178. //--repair--             case 1:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
  1179. //--repair--             case 2:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_3,F1_0 ); break;
  1180. //--repair--             case 3:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_4,F1_0 ); break;
  1181. //--repair--             case 4:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_1,F1_0 ); break;
  1182. //--repair--             case 5:    digi_play_sample( SOUND_REPAIR_STATION_FIXING_2,F1_0 ); break;
  1183. //--repair--             }
  1184. //--repair--         
  1185. //--repair--             repair_ship_damage();
  1186. //--repair-- 
  1187. //--repair--         }
  1188. //--repair-- 
  1189. //--repair--         if (current_time >= (delta_time+(F1_0/2)) )    {
  1190. //--repair--             current_time = 0;
  1191. //--repair--             // Find next side...
  1192. //--repair--             side_index++;
  1193. //--repair--             if (side_index >= 6 ) return 1;
  1194. //--repair--             next_side = sidelist[side_index];
  1195. //--repair--     
  1196. //--repair--             refuel_calc_deltas(obj, next_side, repair_seg);
  1197. //--repair--         }
  1198. //--repair-- 
  1199. //--repair--     } else {
  1200. //--repair--         fix factor, p,b,h;    
  1201. //--repair--         vms_angvec av;
  1202. //--repair-- 
  1203. //--repair--         factor = fixdiv( current_time,delta_time );
  1204. //--repair-- 
  1205. //--repair--         // Find object's current position
  1206. //--repair--         obj->pos = delta_pos;
  1207. //--repair--         vm_vec_scale( &obj->pos, factor );
  1208. //--repair--         vm_vec_add2( &obj->pos, &start_pos );
  1209. //--repair--             
  1210. //--repair--         // Find object's current orientation
  1211. //--repair--         p    = fixmul(delta_angles.p,factor);
  1212. //--repair--         b    = fixmul(delta_angles.b,factor);
  1213. //--repair--         h    = fixmul(delta_angles.h,factor);
  1214. //--repair--         av.p = (fixang)p + start_angles.p;
  1215. //--repair--         av.b = (fixang)b + start_angles.b;
  1216. //--repair--         av.h = (fixang)h + start_angles.h;
  1217. //--repair--         vm_angles_2_matrix(&obj->orient,&av);
  1218. //--repair-- 
  1219. //--repair--     }
  1220. //--repair-- 
  1221. //--repair--     update_object_seg(obj);        //update segment
  1222. //--repair-- 
  1223. //--repair--     return 0;
  1224. //--repair-- }
  1225. //--repair-- 
  1226. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1227. //--repair-- //do the repair center for this frame
  1228. //--repair-- void do_repair_sequence(object *obj)
  1229. //--repair-- {
  1230. //--repair--     Assert(obj == RepairObj);
  1231. //--repair-- 
  1232. //--repair--     if (refuel_do_repair_effect( obj, 0, FuelStationSeg )) {
  1233. //--repair--         if (Players[Player_num].shields < MAX_SHIELDS)
  1234. //--repair--             Players[Player_num].shields = MAX_SHIELDS;
  1235. //--repair--         obj->control_type = save_control_type;
  1236. //--repair--         obj->movement_type = save_movement_type;
  1237. //--repair--         disable_repair_center=1;
  1238. //--repair--         RepairObj = NULL;
  1239. //--repair-- 
  1240. //--repair-- 
  1241. //--repair--         //the two lines below will spit the player out of the rapair center,
  1242. //--repair--         //but what happen is that the ship just bangs into the door
  1243. //--repair--         //if (obj->movement_type == MT_PHYSICS)
  1244. //--repair--         //    vm_vec_copy_scale(&obj->mtype.phys_info.velocity,&obj->orient.fvec,i2f(200));
  1245. //--repair--     }
  1246. //--repair-- 
  1247. //--repair-- }
  1248. //--repair-- 
  1249. //--repair-- //    ----------------------------------------------------------------------------------------------------------
  1250. //--repair-- //see if we should start the repair center
  1251. //--repair-- void check_start_repair_center(object *obj)
  1252. //--repair-- {
  1253. //--repair--     if (RepairObj != NULL) return;        //already in repair center
  1254. //--repair-- 
  1255. //--repair--     if (Lsegments[obj->segnum].special_type & SS_REPAIR_CENTER) {
  1256. //--repair-- 
  1257. //--repair--         if (!disable_repair_center) {
  1258. //--repair--             //have just entered repair center
  1259. //--repair-- 
  1260. //--repair--             RepairObj = obj;
  1261. //--repair--             repair_save_uvec = obj->orient.uvec;
  1262. //--repair-- 
  1263. //--repair--             repair_rate = fixmuldiv(FULL_REPAIR_RATE,(MAX_SHIELDS - Players[Player_num].shields),MAX_SHIELDS);
  1264. //--repair-- 
  1265. //--repair--             save_control_type = obj->control_type;
  1266. //--repair--             save_movement_type = obj->movement_type;
  1267. //--repair-- 
  1268. //--repair--             obj->control_type = CT_REPAIRCEN;
  1269. //--repair--             obj->movement_type = MT_NONE;
  1270. //--repair-- 
  1271. //--repair--             FuelStationSeg    = Lsegments[obj->segnum].special_segment;
  1272. //--repair--             Assert(FuelStationSeg != -1);
  1273. //--repair-- 
  1274. //--repair--             if (refuel_do_repair_effect( obj, 1, FuelStationSeg )) {
  1275. //--repair--                 Int3();        //can this happen?
  1276. //--repair--                 obj->control_type = CT_FLYING;
  1277. //--repair--                 obj->movement_type = MT_PHYSICS;
  1278. //--repair--             }
  1279. //--repair--         }
  1280. //--repair--     }
  1281. //--repair--     else
  1282. //--repair--         disable_repair_center=0;
  1283. //--repair-- 
  1284. //--repair-- }
  1285.  
  1286. //    --------------------------------------------------------------------------------------------
  1287. void disable_matcens(void)
  1288. {
  1289.     int    i;
  1290.  
  1291.     for (i=0; i<Num_robot_centers; i++) {
  1292.         Station[i].Enabled = 0;
  1293.         Station[i].Disable_time = 0;
  1294.     }
  1295. }
  1296.  
  1297. //    --------------------------------------------------------------------------------------------
  1298. //    Initialize all materialization centers.
  1299. //    Give them all the right number of lives.
  1300. void init_all_matcens(void)
  1301. {
  1302.     int    i;
  1303.  
  1304.     for (i=0; i<Num_fuelcenters; i++)
  1305.         if (Station[i].Type == SEGMENT_IS_ROBOTMAKER) {
  1306.             Station[i].Lives = 3;
  1307.             Station[i].Enabled = 0;
  1308.             Station[i].Disable_time = 0;
  1309. #ifndef NDEBUG
  1310. {
  1311.             //    Make sure this fuelcen is pointed at by a matcen.
  1312.             int    j;
  1313.             for (j=0; j<Num_robot_centers; j++) {
  1314.                 if (RobotCenters[j].fuelcen_num == i)
  1315.                     break;
  1316.             }
  1317.             Assert(j != Num_robot_centers);
  1318. }
  1319. #endif
  1320.  
  1321.         }
  1322.  
  1323. #ifndef NDEBUG
  1324.     //    Make sure all matcens point at a fuelcen
  1325.     for (i=0; i<Num_robot_centers; i++) {
  1326.         int    fuelcen_num = RobotCenters[i].fuelcen_num;
  1327.  
  1328.         Assert(fuelcen_num < Num_fuelcenters);
  1329.         Assert(Station[fuelcen_num].Type == SEGMENT_IS_ROBOTMAKER);
  1330.     }
  1331. #endif
  1332.  
  1333. }
  1334.